"""
WeatherSponge
Copyright (c) 2008 Marlon B van der Linde <marlon@mbvdl.net>
See 'COPYING' for license

"""

import adodb as ado
import sys

class Storage(object):
	"""
	Storage is a database class to handle input, output and searching
	for the WeatherSponge application
	
	"""

	data = {}
	db = None
	dataFields = ('pubtitle', 'pubdate', 'barometer', 'windspeed', \
				  'dewpoint', 'winddirection', 'visibility', 'humidity', \
				  'windchill', 'heatindex', 'temp', 'slot')
	dbTable = 'sponge'

	def __init__(self, conParams):
		"""
		Check for existence of required keys, and connect to database
		
		@param conParams: a dict containing the database parameters
		@type conParams: dict

		"""

		dbopts = ('dbhost','dbuser','dbpasswd','dbname')
		keyFail = False
		for key in conParams.iterkeys():
			if not key in dbopts:
				keyFail = True;
		if keyFail:
			print "Storage Class Init: Incorrect Keys Supplied or missing keys"
			raise SystemExit(3)
		
		try:
			self.db = ado.NewADOConnection('mysql')
			self.db.Connect(conParams["dbhost"], conParams["dbuser"], conParams["dbpasswd"], conParams["dbname"])
		except:
			print "Storage.__init__ db connection failed: " + str(sys.exc_info()[1])
			raise SystemExit(4)

		#self.data.fromkeys(self.dataFields)
		self.data.update((k, None) for k in self.dataFields)


	def debug(self):
		print self.data


	def __getitem__(self, key):
		"""
		Special method to get data items from this class directly

		@returns: string containing requested key - self.conParams[key]:
		@rtype: str
		
		"""
		
		if not key in self.dataFields:
			return False

		return self.data[key]


	def __setitem__(self, key, item):
		"""
		Special method to set data items directly
		
		"""
		if not key in self.dataFields:
			return False

		self.data[key] = item

	
	def showAll(self):
		"""
		Print all keys and values of the current self.data
		This is for debugging and testing only
		
		"""
		for k, v in self.data.iteritems():
			print "[k] " + k
			print "[v] " + v

	
	def insertRow(self):
		"""
		Inserts whatever is currently in self.data into the database as a new row

		@return: row ID or None if this operation failed
		@rtype: int or None

		"""
		fail = None
		missingVals = []
		for k, v in self.data.iteritems():
			if v == None:
				missingVals.append(k)
				fail = 1

		if fail:
			print "Warning: Values Missing For Keys: " + str(missingVals)
			return None
		
		#TODO hardcoded table name must go, use self.dbTable
		sql = "INSERT INTO sponge (`barometer`, `dewpoint`, `heatindex`, `humidity`, " \
		"`pubdate`, `pubtitle`, `temp`, `visibility`, `windchill`, `winddirection`, " \
		"`windspeed`, `slot`) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)"
		
		c = self.db.Execute(sql, 
		(self.data['barometer'], self.data['dewpoint'], self.data['heatindex'],
		self.data['humidity'], self.data['pubdate'], self.data['pubtitle'], self.data['temp'],
		self.data['visibility'], self.data['windchill'], self.data['winddirection'],
		self.data['windspeed'], self.data['slot']))
		
		if c == None:
			print "Insert Problem: " + self.db.ErrorMsg()
			return None
		
		return c.Insert_ID()


	def findRow(self, matchField, matchData, exact=0):
		"""
		Find the row containing 'matchData' in it's 'matchField' field, and return
		the id to this row

		@param matchField: The field name to search for matchData
		@type matchField: str

		@param matchData: The data to search for in matchField
		@type matchData: mixed

		@param exact: The option to search the db for an exact match or a "like"
		@type exact: int

		@return: Returns the id of the matching field or None if not found
		@rtype: int or None

		"""
		
		if not matchField in self.dataFields:
			print "%s not found in dataset. Mismatch" % (matchField, )
			return None
		#TODO: use self.dbTable instead of hardcoded table name
		if exact:
			sql = "SELECT id FROM %s WHERE %s = %%s" % (self.dbTable, matchField, )
		else:
			matchData = '%' + matchData + '%'
			sql = "SELECT id FROM %s WHERE %s LIKE %%s" % (self.dbTable, matchField, )

		c = self.db.Execute(sql, (matchData, ))
		if not c:
			print "findRow() problem: " + self.db.ErrorMsg()
			return None
		
		x = c.FetchRow()
		if x:
			return x[0]
		else:
			return None



	def getRow(self, rowID):
		"""
		Loads the contents of rowID into self.data for further work

		@param rowID: The id of the record to fetch and load
		@type rowID: int
		
		"""
		
		sql = "SELECT * FROM %s WHERE id = %s" % (self.dbTable, rowID)

		c = self.db.Execute(sql)
		if not c:
			print "Illness in getRow() GetAssoc : " + self.db.ErrorMsg()
			return None
		try:
			foo = c.GetRowAssoc(0)
			self.data.update(foo)
		except:
			print "Illness in getRow()"
			return None

		return None


if __name__ == "__main__":
	print "Rather Try Importing This"

